package me.algo.thread;

import java.lang.management.ManagementFactory;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

/**
 * @author guozheng
 * @date 2024/3/23
 */
public class M1 {
    public static void main(String[] args) throws InterruptedException {

        CountDownLatch countDownLatch = new CountDownLatch(1);
        OddEvenPrinter printer = new OddEvenPrinter(0, 20000);
        Thread even = new Thread(() -> {
            try {
                countDownLatch.await();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            printer.printEven();
        }, "even-thread");
        even.start();
        Thread odd = new Thread(() -> {
            try {
                countDownLatch.await();
                printer.printOdd();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }

        }, "odd-thread");
        odd.start();
        countDownLatch.countDown();
        TimeUnit.HOURS.sleep(1);
    }


    private static class OddEvenPrinter{
        private volatile int num;

        private final int maxNum;

        public OddEvenPrinter(int num, int maxNum) {
            this.num = num;
            this.maxNum = maxNum;
        }


        private final Object lock = new Object();

        public void printEven() {
            synchronized (lock) {
                while (num < maxNum) {
                    if (num % 2 == 0) {
                        System.out.println(STR."Even=\{num}");
                        num++;
                        lock.notify();
                        try {
                            TimeUnit.SECONDS.sleep(1);
                        } catch (InterruptedException e) {
                            throw new RuntimeException(e);
                        }
                    } else {
                        try {
                            lock.wait();
                        } catch (InterruptedException e) {
                            throw new RuntimeException(e);
                        }
                    }
                }
            }
        }

        public void printOdd() {
            synchronized (lock) {
                while (num < maxNum) {
                    if (num % 2 != 0) {
                        System.out.println(STR."Odd=\{num}");
                        num++;
                        lock.notify();
                    } else {
                        try {
                            lock.wait();
                        } catch (InterruptedException e) {
                            throw new RuntimeException(e);
                        }
                    }
                }
            }
        }
    }

}
